package cn.yx.common.security.webmvc.sms;

import cn.hutool.core.util.StrUtil;
import cn.yx.common.security.properties.SecurityProperties;
import cn.yx.common.security.webmvc.vo.in.PhoneSmsCodeInVo;
import cn.yx.common.web.util.WebUtil;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * <p>手机验证码登录过滤器，包含有手机号和手机验证码。依照UsernamePasswordAuthenticationFilter编写</p>
 *
 * @author Wgssmart
 */
public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final boolean POST_ONLY = true;

    public SmsCodeAuthenticationFilter(SecurityProperties securityProperties) {
        // 设置短信登录url，必须是post请求
        super(new AntPathRequestMatcher(securityProperties.getSmsCode().getLoginUrl(), HttpMethod.POST.name()));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (POST_ONLY && !HttpMethod.POST.name().equals(request.getMethod())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        PhoneSmsCodeInVo phoneSmsCodeInVo = WebUtil.getRequestData(request, PhoneSmsCodeInVo.class);
        String phone = getPhone(phoneSmsCodeInVo);
        String smsCode = getSmsCode(phoneSmsCodeInVo);
        // 将包含有手机号和验证码的token交给SmsCodeAuthenticationProvider进行验证
        SmsCodeAuthenticationToken authRequest = new SmsCodeAuthenticationToken(phone, smsCode);
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    /**
     * 获取手机号
     *
     * @param phoneSmsCodeInVo
     * @return
     */
    private String getPhone(PhoneSmsCodeInVo phoneSmsCodeInVo) {
        String phone = phoneSmsCodeInVo.getPhone();
        if (StrUtil.isEmpty(phone)) {
            phone = "";
        }
        return phone.trim();
    }

    /**
     * 获取手机验证码
     *
     * @param phoneSmsCodeInVo
     * @return
     */
    private String getSmsCode(PhoneSmsCodeInVo phoneSmsCodeInVo) {
        String smsCode = phoneSmsCodeInVo.getSmsCode();
        if (StrUtil.isEmpty(smsCode)) {
            smsCode = "";
        }
        return smsCode.trim();
    }

}